package cn.blnp.net.flowable.multiple.child;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Lists;
import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ExecutionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <h3>子流程多实例实战案例</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/5/22 16:29
 */
@Slf4j
@SpringBootTest
public class MultipleInsChildFlowTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private ManagementService managementService;

    //初始化秘书信息
    private Map<String, String> secretaryMap = MapUtil.builder(new HashMap<String, String>())
            .put("张三", "555")
            .put("李四", "666")
            .put( "王五", "777")
            .put( "赵六", "888")
            .put( "安琪拉", "999")
            .build();

    /**
     *  <h2>多实例子流程应用</h2>
     *  <p>
     *      子流程可以分解复杂流程，将其划分为多个不同的阶段，便于实现对流程的整体把握。子流程在实际需求场景中应用比较广泛，同样支持多实例。尽管可以将单个活动设置为多实例，
     *  但实际需求场景中经常要求对一组活动使用多实例。例如，多部门联合发文流程，公文起草之后需要多部门协作审批，只有各部门都审批完成后才能进入下一环节。多部门审批具有通用性，
     *  并且要求可以同时进行，因此可以采用多实例子流程来实现，如图所示。
     *      <b>流程定义文件：</b>{@link flow/multiSubprocessProcess.bpmn20.xml}<br/>
     *      <b>流程预览图：</b><br/>
     *      <img src="https://cdn4.winhlb.com/2025/05/22/682ee1fa52823.png" />
     *  </p>
     *
     **/
    @Test
    public void test() throws InterruptedException {
        Deployment deploy = repositoryService.createDeployment()
                .name("子流程多实例实战-演示案例")
                .addClasspathResource("flow/multiSubprocessProcess.bpmn20.xml")
                .deploy();
        log.info("部署流程定义：{}", deploy.getId());
        ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        log.info("流程定义编号：{}", procDef.getId());

        //启动流程实例
        ProcessInstance mainProcInst = runtimeService.startProcessInstanceById(procDef.getId());

        ExecutionQuery executionQuery = runtimeService.createExecutionQuery()
                .processInstanceId(mainProcInst.getId());
        //查询执行实例
        List<Execution> executionList1 = executionQuery.list();
        log.info("主流程发起后，执行实例数为：{}，分别为：{}", executionList1.size(),
                JSON.toJSONString(executionList1, executionFilter));
        TaskQuery taskQuery = taskService.createTaskQuery()
                .processInstanceId(mainProcInst.getId());
        //查询主流程第一个任务
        Task firstTaskOfMainProcess = taskQuery.singleResult();
        log.info("主流程当前所在节点为：{}", firstTaskOfMainProcess.getName());
        //设置主流程的流程变量
        List<String> assigneeList = Lists.newArrayList("张三", "李四",
                "王五", "赵六", "安琪拉");
        Map<String, Object> varMap1 = MapUtil.builder(new HashMap<String, Object>())
                .put("assigneeList", assigneeList)
                .build();

        //完成主流程第一个任务，启动子流程
        taskService.complete(firstTaskOfMainProcess.getId(), varMap1);
        //查询执行实例
        List<Execution> executionList2 = executionQuery.list();
        log.info("子流程发起后，执行实例数为：{}，分别为：{}", executionList2.size(),
                JSON.toJSONString(executionList2, executionFilter));
        //查询子流程第一个节点的任务，并依次完成
        List<Task> firstTasksOfSubProcess = taskQuery.list();
        for (Task firstTaskOfSubProcess : firstTasksOfSubProcess) {
            log.info("子流程当前所在节点为：{}，taskId：{}，办理人：{}",
                    firstTaskOfSubProcess.getName(), firstTaskOfSubProcess.getId(),
                    firstTaskOfSubProcess.getAssignee());
            Map<String, Object> varMap2 = MapUtil.builder(new HashMap<String, Object>())
                    .put("nextUserId", secretaryMap.get(firstTaskOfSubProcess.getAssignee()))
                            .build();
            taskService.complete(firstTaskOfSubProcess.getId(), varMap2);
        }
        //查询子流程第二个节点的任务，并依次完成
        List<Task> secondTasksOfSubProcess = taskQuery.list();
        for (Task secondTaskOfSubProcess : secondTasksOfSubProcess) {
            log.info("子流程当前所在节点为：{}，taskId：{}，办理人：{}",
                    secondTaskOfSubProcess.getName(), secondTaskOfSubProcess.getId(),
                    secondTaskOfSubProcess.getAssignee());
            taskService.complete(secondTaskOfSubProcess.getId());
        }
        Thread.sleep(500);
        //查询执行实例
        List<Execution> executionList3 = executionQuery.list();
        log.info("子流程结束后，执行实例数为：{}，执行实例信息为：{}", executionList3.size(),
                JSON.toJSONString(executionList3, executionFilter));
        //查询主流程第二个任务
        Task secondTaskOfMainProcess = taskQuery.singleResult();
        log.info("主流程所在当前节点为：" + secondTaskOfMainProcess.getName());
        taskService.complete(secondTaskOfMainProcess.getId());
        //查询执行实例
        List<Execution> executionList4 = executionQuery.list();
        log.info("主流程结束后，执行实例数为：{}，执行实例信息为：{}", executionList4.size(),
                JSON.toJSONString(executionList4, executionFilter));

        /**
         *  演示结果：
         *  2025-05-22 16:52:42.370  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 部署流程定义：1edbbe42-36ea-11f0-aeee-50ebf6ec8f6d
         * 2025-05-22 16:52:42.375  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 流程定义编号：multiSubprocessProcess:3:1f449235-36ea-11f0-aeee-50ebf6ec8f6d
         * 2025-05-22 16:52:42.390  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 流程启动 | 实例ID:1f4d1db7-36ea-11f0-aeee-50ebf6ec8f6d | 定义ID:multiSubprocessProcess:3:1f449235-36ea-11f0-aeee-50ebf6ec8f6d
         * 2025-05-22 16:52:42.392 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfMainProcess
         * 2025-05-22 16:52:42.397 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfMainProcess
         * 2025-05-22 16:52:42.409  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f5003eb-36ea-11f0-aeee-50ebf6ec8f6d | 名称:起草公文 | 处理人:null
         * 2025-05-22 16:52:42.745  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 主流程发起后，执行实例数为：2，分别为：[{"id":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"firstUserTaskOfMainProcess","id":"1f4d1db7-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false}]
         * 2025-05-22 16:52:42.762  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 主流程当前所在节点为：起草公文
         * 2025-05-22 16:52:42.801 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:subProcess | ID:subProcess1
         * 2025-05-22 16:52:42.802 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:subProcess | ID:subProcess1
         * 2025-05-22 16:52:42.802 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:subProcess | ID:subProcess1
         * 2025-05-22 16:52:42.802 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:subProcess | ID:subProcess1
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:subProcess | ID:subProcess1
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfSubProcess
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfSubProcess
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfSubProcess
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfSubProcess
         * 2025-05-22 16:52:42.803 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:startEvent | ID:startEventOfSubProcess
         * 2025-05-22 16:52:42.804 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfSubProcess
         * 2025-05-22 16:52:42.808  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f8c97ef-36ea-11f0-aeee-50ebf6ec8f6d | 名称:经理审批 | 处理人:张三
         * 2025-05-22 16:52:42.808 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfSubProcess
         * 2025-05-22 16:52:42.809  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f8d5b43-36ea-11f0-aeee-50ebf6ec8f6d | 名称:经理审批 | 处理人:李四
         * 2025-05-22 16:52:42.809 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfSubProcess
         * 2025-05-22 16:52:42.809  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f8d5b47-36ea-11f0-aeee-50ebf6ec8f6d | 名称:经理审批 | 处理人:王五
         * 2025-05-22 16:52:42.809 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfSubProcess
         * 2025-05-22 16:52:42.810  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f8d5b4b-36ea-11f0-aeee-50ebf6ec8f6d | 名称:经理审批 | 处理人:赵六
         * 2025-05-22 16:52:42.810 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:firstUserTaskOfSubProcess
         * 2025-05-22 16:52:42.810  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1f8d825f-36ea-11f0-aeee-50ebf6ec8f6d | 名称:经理审批 | 处理人:安琪拉
         * 2025-05-22 16:52:42.927  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程发起后，执行实例数为：12，分别为：[{"id":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"subProcess1","id":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false},{"activityId":"subProcess1","id":"1f8bfb8b-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"subProcess1","id":"1f8bfb8c-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"subProcess1","id":"1f8bfb8d-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"subProcess1","id":"1f8bfb8e-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"subProcess1","id":"1f8bfb8f-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bad67-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":true},{"activityId":"firstUserTaskOfSubProcess","id":"1f8c49b7-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bfb8b-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false},{"activityId":"firstUserTaskOfSubProcess","id":"1f8c49ba-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bfb8c-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false},{"activityId":"firstUserTaskOfSubProcess","id":"1f8c49bd-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bfb8d-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false},{"activityId":"firstUserTaskOfSubProcess","id":"1f8c49c0-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bfb8e-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false},{"activityId":"firstUserTaskOfSubProcess","id":"1f8c70d3-36ea-11f0-aeee-50ebf6ec8f6d","parentId":"1f8bfb8f-36ea-11f0-aeee-50ebf6ec8f6d","processInstanceId":"1f4c8176-36ea-11f0-aeee-50ebf6ec8f6d","scope":false}]
         * 2025-05-22 16:52:42.932  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：经理审批，taskId：1f8c97ef-36ea-11f0-aeee-50ebf6ec8f6d，办理人：张三
         * 2025-05-22 16:52:42.954 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfSubProcess
         * 2025-05-22 16:52:42.957  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1fa37b99-36ea-11f0-aeee-50ebf6ec8f6d | 名称:秘书盖章 | 处理人:555
         * 2025-05-22 16:52:43.006  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：经理审批，taskId：1f8d5b43-36ea-11f0-aeee-50ebf6ec8f6d，办理人：李四
         * 2025-05-22 16:52:43.039 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfSubProcess
         * 2025-05-22 16:52:43.042  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1fb09a05-36ea-11f0-aeee-50ebf6ec8f6d | 名称:秘书盖章 | 处理人:666
         * 2025-05-22 16:52:43.091  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：经理审批，taskId：1f8d5b47-36ea-11f0-aeee-50ebf6ec8f6d，办理人：王五
         * 2025-05-22 16:52:43.108 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfSubProcess
         * 2025-05-22 16:52:43.111  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1fbb2161-36ea-11f0-aeee-50ebf6ec8f6d | 名称:秘书盖章 | 处理人:777
         * 2025-05-22 16:52:43.135  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：经理审批，taskId：1f8d5b4b-36ea-11f0-aeee-50ebf6ec8f6d，办理人：赵六
         * 2025-05-22 16:52:43.152 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfSubProcess
         * 2025-05-22 16:52:43.153  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1fc1b11d-36ea-11f0-aeee-50ebf6ec8f6d | 名称:秘书盖章 | 处理人:888
         * 2025-05-22 16:52:43.173  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：经理审批，taskId：1f8d825f-36ea-11f0-aeee-50ebf6ec8f6d，办理人：安琪拉
         * 2025-05-22 16:52:43.197 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfSubProcess
         * 2025-05-22 16:52:43.201  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1fc8b609-36ea-11f0-aeee-50ebf6ec8f6d | 名称:秘书盖章 | 处理人:999
         * 2025-05-22 16:52:43.238  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：秘书盖章，taskId：1fa37b99-36ea-11f0-aeee-50ebf6ec8f6d，办理人：555
         * 2025-05-22 16:52:43.249 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:endEvent | ID:endEventOfSubProcess
         * 2025-05-22 16:52:43.319  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：秘书盖章，taskId：1fb09a05-36ea-11f0-aeee-50ebf6ec8f6d，办理人：666
         * 2025-05-22 16:52:43.328 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:endEvent | ID:endEventOfSubProcess
         * 2025-05-22 16:52:43.353  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：秘书盖章，taskId：1fbb2161-36ea-11f0-aeee-50ebf6ec8f6d，办理人：777
         * 2025-05-22 16:52:43.361 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:endEvent | ID:endEventOfSubProcess
         * 2025-05-22 16:52:43.407  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：秘书盖章，taskId：1fc1b11d-36ea-11f0-aeee-50ebf6ec8f6d，办理人：888
         * 2025-05-22 16:52:43.427 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:endEvent | ID:endEventOfSubProcess
         * 2025-05-22 16:52:43.487  INFO 14504 --- [           main] c.b.n.f.m.c.MultipleInsChildFlowTest     : 子流程当前所在节点为：秘书盖章，taskId：1fc8b609-36ea-11f0-aeee-50ebf6ec8f6d，办理人：999
         * 2025-05-22 16:52:43.492 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:endEvent | ID:endEventOfSubProcess
         * 2025-05-22 16:52:43.540 DEBUG 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 节点进入 | 类型:userTask | ID:secondUserTaskOfMainProcess
         * 2025-05-22 16:52:43.541  INFO 14504 --- [           main] c.b.n.f.config.FlowableLoggingListener   : 任务创建 | ID:1ffd0cac-36ea-11f0-aeee-50ebf6ec8f6d | 名称:公文下发 | 处理人:null
         **/
    }

    SimplePropertyPreFilter executionFilter = new SimplePropertyPreFilter(Execution.class,
            "id", "parentId", "processInstanceId", "scope", "activityId");
}
